﻿// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable CommentTypo
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
// ReSharper disable StringLiteralTypo
// ReSharper disable UnusedMember.Global
// ReSharper disable UseNameofExpression

/* AttendanceManager.cs -- менеджер регистрации событий книговыдачи
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System;
using System.Collections.Generic;
using System.Linq;

using AM;

using Istu.NewModel.Interfaces;

using LinqToDB;
using LinqToDB.Data;

#endregion

#nullable enable

namespace Istu.NewModel.Implementation;

/// <summary>
/// Менеджер регистрации событий книговыдачи.
/// </summary>
public sealed class AttendanceManager
    : IAttendanceManager
{
    #region Properties

    /// <summary>
    /// Кладовка.
    /// </summary>
    public Storehouse Storehouse { get; }

    #endregion

    #region Construction

    /// <summary>
    /// Конструктор.
    /// </summary>
    public AttendanceManager
        (
            Storehouse storehouse
        )
    {
        Sure.NotNull (storehouse);

        Storehouse = storehouse;
    }

    #endregion

    #region Private members

    private DataConnection? _dataConnection;

    private DataConnection _GetDb() => _dataConnection ??= Storehouse.GetKladovka();

    #endregion

    #region IAttendanceManager members

    /// <inheritdoc cref="IAttendanceManager.RegisterAttendance"/>
    public void RegisterAttendance
        (
            Attendance info
        )
    {
        Sure.NotNull (info);

        var db = _GetDb();
        db.Insert (info);
    }

    /// <inheritdoc cref="IAttendanceManager.RegisterAttendances"/>
    public void RegisterAttendances
        (
            IEnumerable<Attendance> attendances
        )
    {
        Sure.NotNull (attendances);

        var database = _GetDb();
        database.BulkCopy (attendances);
    }

    /// <inheritdoc cref="IAttendanceManager.GetAttendances"/>
    public Attendance[] GetAttendances
        (
            string ticket
        )
    {
        Sure.NotNullNorEmpty (ticket);

        var database = _GetDb();
        var attendances = database.GetAttendances();
        var result = attendances
            .Where (attendance => attendance.Ticket == ticket)
            .ToArray();

        return result;
    }

    /// <inheritdoc cref="IAttendanceManager.GetLastAttendance"/>
    public Attendance? GetLastAttendance
        (
            string ticket
        )
    {
        Sure.NotNullNorEmpty (ticket);

        var db = _GetDb();
        var attendances = db.GetAttendances();
        var result = attendances
            .Where (attendance => attendance.Ticket == ticket)
            .OrderByDescending (attendance => attendance.Moment)
            .FirstOrDefault();

        return result;
    }

    /// <inheritdoc cref="IAttendanceManager.GetLastReaders"/>
    public Reader[] GetLastReaders
        (
            int howMany = 200
        )
    {
        Sure.Positive (howMany);

        var db = _GetDb();
        var attendances = db.GetAttendances();
        var readers = db.GetReaders();
        var result = readers.Join
                (
                    attendances.Where (attendance => attendance.Type == "a")
                        .OrderByDescending (attendance => attendance.Moment),
                    reader => reader.Ticket,
                    attendance => attendance.Ticket,
                    (reader, attendance) => reader
                )
            .Take (howMany)
            .ToArray()
            .Distinct (new ReaderComparer())
            .ToArray();

        return result;
    }

    #endregion

    #region IDisposable members

    /// <inheritdoc cref="IDisposable.Dispose"/>
    public void Dispose()
    {
        _dataConnection?.Dispose();
        _dataConnection = null;
    }

    #endregion
}
